/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <stdlib.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/reboot.h>

#include <nfc_t2t_lib.h>
#include <nfc/ndef/msg.h>
#include <nfc/ndef/text_rec.h>
#include <zephyr/drivers/pwm.h>
#include <dk_buttons_and_leds.h>
#include <zephyr/drivers/gpio.h>

#define MAX_REC_COUNT		2
#define NDEF_MSG_BUF_SIZE	256

#define NFC_FIELD_LED		DK_LED1

static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));
#define MIN_PERIOD PWM_SEC(1U) / 128U
#define MAX_PERIOD 400000000

/* Text message in English with its language code. */


static char* MainMsgHd = "zsy,hallo world";
static  uint8_t MainPayload[64] = "zsy,hallo!!";
static const uint8_t MainCode[8] = "ch ";


/* Text message in Norwegian with its language code. */
static const uint8_t yq_payload[64] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
static const uint8_t yq_code[8]= "yq";



/* Buffer used to hold an NFC NDEF message. */
static uint8_t ndef_msg_buf[2][NDEF_MSG_BUF_SIZE];

int activeNfcDev = 0;

//button
static struct gpio_callback button_cb_data;
static struct gpio_callback button_cb_data1;


#define SW0_NODE	DT_ALIAS(sw0)
#define SW1_NODE	DT_ALIAS(sw1)

static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,{0});
static const struct gpio_dt_spec button1 = GPIO_DT_SPEC_GET_OR(SW1_NODE, gpios,{0});


static void nfc_callback(void *context,
			 nfc_t2t_event_t event,
			 const uint8_t *data,
			 size_t data_length)
{

	printk("nfc_callback this is nfc cbk! event[%d]\n",event);

	ARG_UNUSED(context);
	ARG_UNUSED(data);
	ARG_UNUSED(data_length);

	switch (event) {
	case NFC_T2T_EVENT_FIELD_ON:
		dk_set_led_on(NFC_FIELD_LED);
		break;
	case NFC_T2T_EVENT_FIELD_OFF:
		dk_set_led_off(NFC_FIELD_LED);
		break;
	default:
		break;
	}
}



/**
 * @brief Function for create the NDEF text message.
 */
static int create_new_NFC_msg(char *Keystr,int inx)
{

	static char* buf = ndef_msg_buf[0];//ndef_msg_buf[falg];
	int len = NDEF_MSG_BUF_SIZE;//sizeof(ndef_msg_buf);

	// if(buf){
	// 	k_free(buf);	
	// 	buf = NULL;
	// }
	// buf = k_malloc(NDEF_MSG_BUF_SIZE);

	int err;
	NFC_NDEF_MSG_DEF(nfc_text_msg, MAX_REC_COUNT);

	sprintf(MainPayload,"zsy,hallo world-[%s] shifting:%d !!!",Keystr,inx);
	// def mesg
	printk("11111--buf[%p]MainPayload[%s]\n",buf,MainPayload);

	//define record 1
	NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_en_text_rec, UTF_8, MainCode,strlen(MainCode), MainPayload, strlen(MainPayload));

	//define recoresd 2
	NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_yq_text_rec,UTF_8,yq_code, strlen(yq_code), yq_payload, strlen(yq_payload));

	//add record 1
	err = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg), &NFC_NDEF_TEXT_RECORD_DESC(nfc_en_text_rec));
	if (err < 0) {
		printk("Cannot add first record!\n");
		return err;
	}

	//add record 2
	err = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg), &NFC_NDEF_TEXT_RECORD_DESC(nfc_yq_text_rec));
	if (err < 0) {
		printk("Cannot add second record!\n");
		return err;
	}

	// setup a mesg instance
	err = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg), buf, &len);
	if (err < 0) {
		printk("Cannot encode message!\n");
	}
	return err;
	/* Set created message as the NFC payload */
	printk("register new payload[%d]\n",len);
	if ((err = nfc_t2t_payload_set(buf, len)) < 0) {
		printk("Cannot set payload!err[%d]\n",err);
	}
	return err;
}

int unitPeriod = (MAX_PERIOD-MIN_PERIOD)/16;
int AverPeriod = (MIN_PERIOD+MAX_PERIOD)/2;

void setLedPwm(int perid)
{

	int pwdPeriod = AverPeriod + perid;
	if(pwdPeriod > MAX_PERIOD || pwdPeriod < MIN_PERIOD){
		printk("novalid period[%u] min:max[%u:%u]\n",pwdPeriod,MIN_PERIOD,MAX_PERIOD);
		return;
	}
	pwm_set_dt(&pwm_led0, pwdPeriod, pwdPeriod / 2U);
	printk("set pwm value :pwdPeriod[%u]\n",pwdPeriod);
}


int leftInx = 0;
int righInx = 0;
int LoadLen = sizeof(ndef_msg_buf);
void button_pressed(const struct device *dev, struct gpio_callback *cb,uint32_t pins)
{
	LoadLen = sizeof(ndef_msg_buf);
	if(righInx) righInx = 0;
	leftInx++;
	printk("Button0 pressed at %" PRIu32 "--righInx[%d]leftInx[%d]\n", k_cycle_get_32(),righInx,leftInx);
	create_new_NFC_msg("left",leftInx);
	setLedPwm((-1)*unitPeriod*leftInx);
}
void button1_pressed(const struct device *dev, struct gpio_callback *cb,uint32_t pins)
{
	LoadLen = sizeof(ndef_msg_buf);
	if(leftInx) leftInx = 0;
	righInx++;
	printk("Button0 pressed at %" PRIu32 "---righInx[%d]leftInx[%d]\n", k_cycle_get_32(),righInx,leftInx);
	create_new_NFC_msg("right",righInx);

	printk("Button1 pressed at %" PRIu32 "\n", k_cycle_get_32());
	setLedPwm(unitPeriod*righInx);
}

int main(void)
{
	int ret;
	uint32_t len = sizeof(ndef_msg_buf);
	uint32_t max_period;
	uint32_t period;
	printk("Starting NFC Text Record example\n");
//button src

	if (!gpio_is_ready_dt(&button)) {
		printk("Error: button device %s is not ready\n", button.port->name);
		return 0;
	}

	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret != 0) {
		printk("Error %d: failed to configure %s pin %d\n", ret, button.port->name, button.pin);
		return 0;
	}

	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
	if (ret != 0) {
		printk("Error %d: failed to configure interrupt on %s pin %d\n",ret, button.port->name, button.pin);
		return 0;
	}

	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);
	printk("Set up button at %s pin %d\n", button.port->name, button.pin);

	// set btn1
	gpio_is_ready_dt(&button1);
	gpio_pin_configure_dt(&button1, GPIO_INPUT);
	gpio_pin_interrupt_configure_dt(&button1, GPIO_INT_EDGE_TO_ACTIVE);
	gpio_init_callback(&button_cb_data1, button1_pressed, BIT(button1.pin));
	gpio_add_callback(button1.port, &button_cb_data1);
	printk("Set up button at %s pin %d\n", button1.port->name, button1.pin);


	printk("pwd led for channel %d...\n", pwm_led0.channel);

	pwm_set_dt(&pwm_led0, AverPeriod, AverPeriod / 2U);

	//goto test;

	printk("Configure LED-pins as outputs \n");
	if (dk_leds_init() < 0) {
		printk("Cannot init LEDs!\n");
		goto fail;
	}

	/* Set up NFC */
	if (nfc_t2t_setup(nfc_callback, NULL) < 0) {
		printk("Cannot setup NFC T2T library!\n");
		goto fail;
	}


	/* Encode welcome message */
	if (create_new_NFC_msg("no btn",0) < 0) {
		printk("Cannot encode message!\n");
		goto fail;
	}

	int err;
	printk("register new payload[%d]\n",len);
	if ((err = nfc_t2t_payload_set(ndef_msg_buf[0], len)) < 0) {
		printk("Cannot set payload!err[%d]\n",err);
	}

	/* Start sensing NFC field */
	if (nfc_t2t_emulation_start() < 0) {
		printk("Cannot start emulation!\n");
		goto fail;
	}
	printk("NFC configuration done\n");

test:
	// while(1){
	// 	k_sleep(K_MSEC(500));
	// 	//printk("this while process\n");
	// 	//pwm_set_dt(&pwm_led0, period, period / 2U);

	// }

	return 0;

fail:
	printk("have error!\n");
	return -EIO;
}
